package com.aneliya.client;

import java.net.SocketException;

import com.aneliya.dao.IUserDAO;
import com.aneliya.model.ErrorType;
import com.aneliya.model.Message;
import com.aneliya.model.MessageType;
import com.aneliya.model.User;
import com.aneliya.server.dispatcher.Dispatcher;

public abstract class ClientListener extends Thread {
	protected IClient client;
	public void setClient(IClient client) {
		this.client = client;
	}
	
	protected Dispatcher dispatcher;
	public void setDispatcher(Dispatcher dispatcher) {
		this.dispatcher = dispatcher;
	}
	
	protected IUserDAO userDAO;
	public void setUserDAO(IUserDAO userDAO) {
		this.userDAO = userDAO;
	}
	
	public abstract void configure() throws SocketException;
	
	public void handleMessage(Message message) {
		switch (message.getMessageType()) {
		case REGISTER:
			handleRegisterMessage(message);
			break;
		case LOGIN:
			handleLoginMessage(message);
			break;
		case LOGOUT:
			handleLogoutMessage(message);
			break;
		case TEXT:
			handleTextMessage(message);
			break;

		default:
			System.out.println("received message of type: " + message.getMessageType());
			break;
		}
	}
	
	private void handleRegisterMessage(Message message) {
		User newUser = (User) message.getMessage();
		
		if (isClientAuthenticatedWithSameUsername(newUser.getUsername())) {
			return;
		} else if (dispatcher.isClientAuthenticated(client)) {
			dispatcher.removeClient(client);
		}
		
		User user = userDAO.getUserByUsername(newUser.getUsername());
		if (user != null) {
			Message errorMessage = new Message("", ErrorType.REGISTER_FAILED);
			errorMessage.setMessageType(MessageType.ERROR);
			
			client.sendMessage(errorMessage);
		} else {
			userDAO.saveUser(newUser);
			client.setUsername(newUser.getUsername());
			dispatcher.addClient(client);
		}
	}

	private void handleLoginMessage(Message message) {
		User loginUser = (User) message.getMessage();
		
		if (isClientAuthenticatedWithSameUsername(loginUser.getUsername())) {
			return;
		} else if (dispatcher.isClientAuthenticated(client)) {
			dispatcher.removeClient(client);
		}
		
		User user  = userDAO.getUserByUsername(loginUser.getUsername());
		if (user != null && 
				user.getUsername().equals(loginUser.getUsername()) &&
				user.getPassword().equals(loginUser.getPassword())) {
			client.setUsername(loginUser.getUsername());
			dispatcher.addClient(client);
		} else {
			Message errorMessage = new Message("", ErrorType.LOGIN_FAILED);
			errorMessage.setMessageType(MessageType.ERROR);
			
			client.sendMessage(errorMessage);
		}
	}

	private void handleLogoutMessage(Message message) {
		User logoutUser = (User) message.getMessage();
		if (isClientAuthenticatedWithSameUsername(logoutUser.getUsername())) {
			dispatcher.removeClient(client);
		}
	}

	private void handleTextMessage(Message message) {
		if (isClientAuthenticatedWithSameUsername(message.getUsername())) {
			dispatcher.dispatchMessage(message);
		}
	}
	
	private Boolean isClientAuthenticatedWithSameUsername(String username) {
		String clientAuthenticatedUsername = client.getUsername();
		Boolean result = clientAuthenticatedUsername != null && 
			clientAuthenticatedUsername.equals(username);
		return result;
	}
	
}
